Dustin Johnson contributes igo8 support.
authorrobertl <robertl>
Thu, 19 Jun 2008 02:25:12 +0000 (02:25 +0000)
committerrobertl <robertl>
Thu, 19 Jun 2008 02:25:12 +0000 (02:25 +0000)
Makefile.in
igo8.c [new file with mode: 0644]
msvc/GPSBabel.vcproj
reference/track/igo8.trk [new file with mode: 0644]
vecs.c

index ac64a381c6492e70cb2595d9fa7b51eaf02aeba4..275ce5b33348ec91f67dd3a7b205c95c3d2f9457 100644 (file)
@@ -58,7 +58,8 @@ ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o pcx.o cetus.o copilot.o \
        yahoo.o unicsv.o wfff_xml.o garmin_txt.o axim_gpb.o gpssim.o \
        wbt-200.o stmsdf.o gtrnctr.o dmtlog.o raymarine.o alan.o vitovtt.o \
        ggv_log.o g7towin.o garmin_gpi.o lmx.o random.o xol.o dg-100.o \
-       navilink.o mtk_logger.o ik3d.o osm.o destinator.o exif.o vidaone.o
+       navilink.o mtk_logger.o ik3d.o osm.o destinator.o exif.o vidaone.o \
+       igo8.o
 
 FMTS=@FMTS@
 
@@ -179,7 +180,7 @@ leaktest:
 
 dep:
        make clean && make EXTRA_CFLAGS="-MMD"  && cat *.d */*.d > /tmp/dep && rm *.d */*.d
-       (echo "internal_styles.c: mkstyle.sh " style/*.style '  ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)' ) >> /tmp/dep
+       echo "internal_styles.c: mkstyle.sh style/*.style ; ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)' ) >> /tmp/dep
        echo Edit Makefile.in and bring in /tmp/dep
 
 $(WEB)/htmldoc-$(DOCVERSION)/readme.html: FORCE
@@ -957,4 +958,5 @@ zlib/trees.o: zlib/trees.c zlib/deflate.h zlib/zutil.h zlib/zlib.h \
   zlib/zconf.h zlib/trees.h
 zlib/uncompr.o: zlib/uncompr.c zlib/zlib.h zlib/zconf.h
 zlib/zutil.o: zlib/zutil.c zlib/zutil.h zlib/zlib.h zlib/zconf.h
-internal_styles.c: mkstyle.sh  style/arc.style style/cambridge.style style/csv.style style/cup.style style/custom.style style/dna.style style/fugawi.style style/garmin301.style style/garmin_poi.style style/geonet.style style/gpsdrive.style style/gpsdrivetrack.style style/gpsman.style style/iblue747.style style/kompass_tk.style style/kompass_wp.style style/ktf2.style style/kwf2.style style/mapconverter.style style/mxf.style style/nima.style style/openoffice.style style/s_and_t.style style/saplus.style style/sportsim.style style/tabsep.style style/tomtom_asc.style style/tomtom_itn.style style/xmap.style style/xmap2006.style style/xmapwpt.style      ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)
+internal_styles.c: mkstyle.sh  style/arc.style style/cambridge.style style/csv.style style/cup.style style/custom.style style/dna.style style/fugawi.style style/garmin301.style style/garmin_poi.style style/geonet.style style/gpsdrive.style style/gpsdrivetrack.style style/gpsman.style style/iblue747.style style/kompass_tk.style style/kompass_wp.style style/ktf2.style style/kwf2.style style/mapconverter.style style/mxf.style style/nima.style style/openoffice.style style/s_and_t.style style/saplus.style style/sportsim.style style/tabsep.style style/tomtom_asc.style style/tomtom_itn.style style/xmap.style style/xmap2006.style style/xmapwpt.style      
+       ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)
diff --git a/igo8.c b/igo8.c
new file mode 100644 (file)
index 0000000..5a4c07f
--- /dev/null
+++ b/igo8.c
@@ -0,0 +1,319 @@
+/*
+    IGO8 Track Format
+
+    Copyright (C) 2008 Dustin Johnson, Dustin@Dustinj.us
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+
+/*
+    iGo8 (*.trk) Format Overview
+
+  |------------------------------| <--\
+  |        ID Block (20B)        |    |
+  |------------------------------|    |
+  |                              |    |
+  |                              |    
+  |                              |    H
+  |                              |    e
+  |                              |    a
+  |    Description Block (256B)  |    d
+  |                              |    e
+  |                              |    r
+  |                              | 
+  |                              |    |
+  |                              |    |
+  |                              |    |
+  |------------------------------| <--/
+  |    Information Block (12B)   |
+  |------------------------------|
+  |          Waypoint 1          |
+  |------------------------------|
+  |          Waypoint 2          |
+  |------------------------------|
+  |          Waypoint 3          |
+  |------------------------------|
+  |             ...              |
+  |------------------------------|
+
+  ID Block: defined by igo8_id_block
+  Description Block: Two null-terminated unicode 2 strings.
+                     The first is the title of the track, 
+                                        the second is the description.
+  Information Block: defined by igo8_information_block
+  Waypoint: defined by igo8_point
+
+*/
+
+#include <ctype.h>
+#include <time.h>
+#include "defs.h"
+
+#define TRUE 1
+#define FALSE 0
+#define FLOAT_TO_INT(x) ((int)((x) + ((x)<0?-0.5:0.5)))
+#define IGO8_HEADER_SIZE (sizeof(igo8_id_block) + 256)
+#define MYNAME "IGO8"
+
+typedef struct _igo8_id_block 
+{
+       gbuint32 unknown_1;
+       gbuint32 unknown_2;
+       gbuint32 unknown_3;
+       gbuint32 track_number;
+       gbuint32 unknown_4;
+} igo8_id_block, *p_igo8_id_block;
+
+typedef struct _igo8_information_block
+{
+       gbuint32 start_time;       // In Unix time
+       gbuint32 zero;             // Doesn't appear to serve a purpose
+       gbuint32 total_file_size;  // In bytes
+} igo8_information_block, *p_igo8_information_block;
+
+typedef struct _igo8_point 
+{
+       gbuint32 unix_time;
+       gbuint32 lon;
+       gbuint32 lat;
+} igo8_point, *p_igo8_point;
+
+static gbfile *igo8_file_in;
+static gbfile *igo8_file_out;
+gbuint32 invented_time;
+gbuint32 point_count;
+
+// Sanity check
+static void igo8_check_type_sizes()
+{
+       if (sizeof(igo8_point) != 12)
+       {
+               fatal(MYNAME ": igo8_point is %ld bytes instead of the required 12.\n",
+                       sizeof(igo8_point));
+       }
+
+       if (sizeof(igo8_information_block) != 12)
+       {
+               fatal(MYNAME ": igo8_information_block is %ld bytes instead of the required 12.\n",
+                       sizeof(igo8_information_block));
+       }
+
+       if (sizeof(igo8_id_block) != 20)
+       {
+               fatal(MYNAME ": igo8_id_block is %ld bytes instead of the required 20.\n",
+                       sizeof(igo8_id_block));
+       }
+}
+
+// Reader initialization callback
+static void igo8_read_init(const char *fname)
+{
+       igo8_file_in = gbfopen_le(fname, "rb", MYNAME);
+       
+       // Make sure that we are in the environment we expect and require
+       igo8_check_type_sizes();
+
+       // Seek past the header and the Information Block
+       gbfseek(igo8_file_in, IGO8_HEADER_SIZE + sizeof(igo8_information_block), SEEK_SET);
+}
+
+// Reader callback
+static void igo8_read(void)
+{
+       waypoint *wpt_tmp;
+       route_head *track_head;
+       igo8_point point;
+
+       track_head = route_head_alloc();
+       track_add_head(track_head);
+
+       while (gbfread(&point, sizeof(point), 1, igo8_file_in) > 0) {
+               wpt_tmp = waypt_new();
+
+               wpt_tmp->latitude = le_read32(&point.lat) / (double)0x800000;
+               wpt_tmp->longitude = le_read32(&point.lon) / (double)0x800000;
+               wpt_tmp->creation_time = le_read32(&point.unix_time);   
+
+               track_add_wpt(track_head, wpt_tmp);
+       }
+}
+
+// Reader close callback
+static void igo8_read_deinit(void)
+{
+       gbfclose(igo8_file_in);
+}
+
+// Writer initialize callback
+static void igo8_write_init(const char *fname)
+{
+       igo8_file_out = gbfopen_le(fname, "wb", MYNAME);
+
+       igo8_check_type_sizes();
+
+       invented_time = 1;
+       point_count = 0;
+}
+
+// Writer close callback
+static void igo8_write_deinit(void)
+{
+       unsigned long normalized_file_size;
+
+       // Seek to the start of the third long in the Information Block, this is
+       // where we will write out the total size of the file.
+       gbfseek(igo8_file_out, IGO8_HEADER_SIZE + sizeof(gbuint32)*2, SEEK_SET);
+
+       // The total size of the file is the number of points written + Information block + Header
+       le_write32(&normalized_file_size, sizeof(igo8_point)*(point_count) + sizeof(igo8_information_block) + IGO8_HEADER_SIZE);
+
+       // Write the size
+       gbfwrite(&normalized_file_size, sizeof(normalized_file_size), 1, igo8_file_out);
+
+       gbfclose(igo8_file_out);
+}
+
+// Write point callback
+static void write_igo8_track_point(const waypoint *wpt)
+{
+       igo8_point point;
+
+       memset(&point, 0, sizeof(point));
+
+       // iGo8 appears to expect a time, if one isn't provided
+       // then we shall make our own, where each point is one
+       // second apart.
+       if (wpt->creation_time == 0)
+       {
+               le_write32(&point.unix_time, invented_time++);
+       }
+       else
+       {
+               le_write32(&point.unix_time, wpt->creation_time);
+       }
+
+       // Write the first part of the Information Block, the start time
+       if (point_count == 0)
+       {
+               gbfwrite(&point, sizeof(point), 1, igo8_file_out);
+       }
+
+       le_write32(&point.lon, FLOAT_TO_INT(wpt->longitude * 0x800000));
+       le_write32(&point.lat, FLOAT_TO_INT(wpt->latitude * 0x800000));
+
+       gbfwrite(&point, sizeof(point), 1, igo8_file_out);
+
+       // Count the number of point printed, we will use this at the end to
+       // finish filling out the Information Block.
+       point_count++;
+}
+
+// This is a sort of hacked together ascii-> unicode 2 converter.  I have no idea
+// if iGo8 even supports real unicode 2, but is does look like it as every ascii
+// character is a short with the ascii character as the least significant 7 bits
+//
+// Please replace this with a much more filled out and correct version if you see 
+// fit.
+unsigned int ascii_to_unicode_2(char* dst, unsigned int dst_max_length, char* src)
+{
+       unsigned int current_src_position = 0;
+       unsigned int current_dst_position = 0;
+       unsigned short current_unicode_char;
+
+       while (src[current_src_position] != '\0' && current_dst_position+4 <= dst_max_length)
+       {
+               le_write16(&current_unicode_char, src[current_src_position]);
+               *(gbuint16*)&dst[current_dst_position] = current_unicode_char;
+               current_src_position++;
+               current_dst_position += 2;
+       }
+
+       if (src[current_src_position] == '\0' && current_dst_position+2 <= dst_max_length)
+       {
+               *(gbuint16*)&dst[current_dst_position] = 0;
+               current_dst_position += 2;
+       }
+
+       return current_dst_position;
+}
+
+void write_header()
+{
+       char header[IGO8_HEADER_SIZE] = {'\0'};
+       igo8_id_block tmp_id_block;
+       p_igo8_id_block id_block = (p_igo8_id_block)header;
+       gbuint32 current_position = 0;
+
+       tmp_id_block.unknown_1 = 0x0000029B;
+       tmp_id_block.unknown_2 = 0x000003E7;
+       tmp_id_block.unknown_3 = 0x00000003;
+
+       // This appears to be a unique number that IDs the track.
+       // It is mono-incrementing and offset by 2 above the track number.
+       // e.g. "Track 1" --> track_number = 3
+       // XXX - Dustin: This might need to be modified to print a number that is user-provided.
+       // XXX - Dustin: My guess is that this number is used as the key for the track color, if 
+       // XXX - Dustin: multiple tracks have the same color they will be colored the same, just
+       // XXX - Dustin: a guess though.
+       tmp_id_block.track_number = 0x00000010;
+       tmp_id_block.unknown_4 = 0x00000001;
+
+       // Byte swap out to the header buffer.
+       le_write32(&id_block->unknown_1, tmp_id_block.unknown_1);
+       le_write32(&id_block->unknown_2, tmp_id_block.unknown_2);
+       le_write32(&id_block->unknown_3, tmp_id_block.unknown_3);
+       le_write32(&id_block->track_number, tmp_id_block.track_number);
+       le_write32(&id_block->unknown_4, tmp_id_block.unknown_4);
+
+       // Move past the ID block, we have just filled it.
+       current_position += sizeof(*id_block);
+
+       // Set the title of the track
+       // XXX - Dustin: This needs to modified to print a title that the user provides.
+       current_position += ascii_to_unicode_2((char*)(header+current_position), IGO8_HEADER_SIZE - current_position, "Title");
+
+       // Set the description of the track
+       // XXX - Dustin: This needs to modified to print a description that the user provides.
+       current_position += ascii_to_unicode_2((char*)(header+current_position), IGO8_HEADER_SIZE - current_position, "Description");
+
+       gbfwrite(&header, IGO8_HEADER_SIZE, 1, igo8_file_out);
+}
+
+// Writer callback
+static void igo8_write(void)
+{
+       write_header();
+       track_disp_all(NULL, NULL, write_igo8_track_point);
+}
+
+// Callback definitions
+ff_vecs_t igo8_vecs = {
+       ff_type_file,
+       { ff_cap_none, ff_cap_read | ff_cap_write, ff_cap_none },
+       igo8_read_init, 
+       igo8_write_init,        
+       igo8_read_deinit,       
+       igo8_write_deinit,      
+       igo8_read,
+       igo8_write,
+       NULL,
+       NULL,
+       CET_CHARSET_UTF8, 
+       1
+};
+
+                
index ed82fee4e7c6b5b42cb211874c4fad0e8e194111..62cadcca7b0672b9327f21812835aff2004c0ee5 100644 (file)
                                >
                        </File>
                        <File
-                               RelativePath="..\ik3d.c">
+                               RelativePath="..\igo8.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\ik3d.c"
+                               >
                        </File>
                        <File
                                RelativePath="..\inifile.c"
diff --git a/reference/track/igo8.trk b/reference/track/igo8.trk
new file mode 100644 (file)
index 0000000..0f95452
Binary files /dev/null and b/reference/track/igo8.trk differ
diff --git a/vecs.c b/vecs.c
index 86b8bd9692820bbc87e7db9de26d3698aacc5be0..4f6dba0e591952ebe1939d303d04a7b42a8c30f9 100644 (file)
--- a/vecs.c
+++ b/vecs.c
@@ -68,6 +68,7 @@ extern ff_vecs_t HsaEndeavourNavigator_vecs;
 extern ff_vecs_t html_vecs;
 extern ff_vecs_t igc_vecs;
 extern ff_vecs_t ignr_vecs;
+extern ff_vecs_t igo8_vecs;
 extern ff_vecs_t kml_vecs;
 extern ff_vecs_t lowranceusr_vecs;
 extern ff_vecs_t mag_fvecs;
@@ -205,11 +206,11 @@ vecs_t vec_list[] = {
                "NMEA 0183 sentences",
                NULL
        },
-        {
-                &kml_vecs,
-                "kml",
-                "Google Earth (Keyhole) Markup Language",
-                "kml"
+       {
+               &kml_vecs,
+               "kml",
+               "Google Earth (Keyhole) Markup Language",
+               "kml"
        },
 #if MAXIMAL_ENABLED
        {
@@ -788,6 +789,12 @@ vecs_t vec_list[] = {
                 "VidaOne GPS for Pocket PC (.gpb)",
                "gpb"
         },
+       {
+               &igo8_vecs,
+               "igo8",
+               "IGO8 .trk",
+               "trk"
+       },
 #endif // MAXIMAL_ENABLED
        {
                NULL,